/** 水印布局方式 */
export type WatermarkLayout = "hexagonal" | "rectangular";

/** 水印文字内容 */
export interface WatermarkText {
  type?: "text";
  text: string;
  fontSize?: number;
  fontFamily?: string;
  fontWeight?: string;
  fontColor?: string;
}

/** 水印图片内容 */
export interface WatermarkImage {
  type?: "image";
  url: string;
  /** 是否应用灰度滤镜 */
  isGrayscale?: boolean;
}

/** 水印内容，可以是单个或混合数组 */
export type WatermarkContent =
  | WatermarkText
  | WatermarkImage
  | Array<WatermarkText | WatermarkImage>;

/** (公开) useWatermark Hook 的配置选项 */
export interface UseWatermarkOptions {
  /** 水印内容的宽度 */
  width: number;
  /** 水印内容的高度 */
  height: number;
  /** 水平间距 */
  gapX: number;
  /** 垂直间距 */
  gapY: number;
  /** 左侧偏移 */
  offsetLeft?: number;
  /** 顶部偏移 */
  offsetTop?: number;
  /** 旋转角度 */
  rotate?: number;
  /** 全局透明度 */
  alpha?: number;
  /** 水印内容 (核心) */
  watermarkContent: WatermarkContent;
  /** (多行文本时) 默认行间距 (当内容为数组时自动计算) */
  lineSpace?: number;
  /** (文本) 默认字体颜色 */
  fontColor?: string;
  /** 布局方式 */
  layout?: WatermarkLayout;
  /** DOM z-index */
  zIndex?: number;
  /** DOM 定位方式 */
  position?: "fixed" | "absolute";
}

type GeneratorOptions = Omit<UseWatermarkOptions, "zIndex" | "position">;
type WatermarkItemInternal = (WatermarkText | WatermarkImage) & { top: number };

interface ObserverData {
  observer: MutationObserver;
  instances: Map<string, () => void>;
}
const observerMap = new WeakMap<HTMLElement, ObserverData>();
let watermarkIdCounter = 0;
const watermarkIdPrefix = "__watermark-";

const debounce = <T extends (...args: any[]) => any>(fn: T, delay: number) => {
  let timer: number | null = null;
  return function (this: any, ...args: Parameters<T>) {
    if (timer) clearTimeout(timer);
    timer = window.setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
};

const observerCallback = (
  mutations: MutationRecord[],
  obs: MutationObserver
) => {
  const targetEl = mutations[0]?.target.parentElement;
  if (!targetEl || !observerMap.has(targetEl)) return;

  const data = observerMap.get(targetEl)!;
  const { instances } = data;
  const affectedIds = new Set<string>();

  for (const mutation of mutations) {
    mutation.removedNodes.forEach((node) => {
      if (node.nodeType === 1 && instances.has((node as HTMLElement).id)) {
        affectedIds.add((node as HTMLElement).id);
      }
    });
    if (
      mutation.type === "attributes" &&
      mutation.attributeName === "style" &&
      mutation.target.nodeType === 1 &&
      instances.has((mutation.target as HTMLElement).id)
    ) {
      affectedIds.add((mutation.target as HTMLElement).id);
    }
  }

  if (affectedIds.size > 0) {
    obs.disconnect();
    affectedIds.forEach((id) => {
      instances.get(id)?.(); // 调用注册的 recreateFn
    });
    obs.observe(targetEl, {
      childList: true,
      attributes: true,
      attributeFilter: ["style"],
      subtree: false,
    });
  }
};

const registerWatermark = (
  id: string,
  el: HTMLElement,
  recreateFn: () => void
) => {
  if (!observerMap.has(el)) {
    const observer = new MutationObserver(observerCallback);
    observer.observe(el, {
      childList: true,
      attributes: true,
      attributeFilter: ["style"],
      subtree: false,
    });
    observerMap.set(el, { observer, instances: new Map() });
  }
  observerMap.get(el)!.instances.set(id, recreateFn);
};

const unregisterWatermark = (id: string, el: HTMLElement) => {
  if (observerMap.has(el)) {
    const data = observerMap.get(el)!;
    data.instances.delete(id);
    if (data.instances.size === 0) {
      data.observer.disconnect();
      observerMap.delete(el);
    }
  }
};

/**
 * 内部画布瓦片生成器
 * @param options 绘图选项
 * @param onFinish 异步完成回调
 */
function _generateWatermarkTileAsync(
  options: GeneratorOptions,
  onFinish: (result: {
    base64Url: string;
    bgWidth: number;
    bgHeight: number;
  }) => void
): void {
  const {
    width,
    height,
    gapX,
    gapY,
    offsetLeft = 0,
    offsetTop = 0,
    rotate = -20,
    alpha = 0.1,
    watermarkContent,
    lineSpace = 16, // 默认行距
    fontColor = "rgba(0,0,0,0.1)",
    layout = "rectangular",
  } = options;

  const isHexagonal = layout === "hexagonal";
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");

  if (!ctx) {
    console.warn("当前环境不支持Canvas, 无法绘制水印");
    onFinish({ base64Url: "", bgWidth: 0, bgHeight: 0 });
    return;
  }

  const ratio = window.devicePixelRatio || 1;

  // 计算画布尺寸
  const canvasWidth = (gapX + width) * ratio;
  const canvasHeight = (gapY + height) * ratio;
  const markWidth = width * ratio;
  const markHeight = height * ratio;

  let finalCanvasWidth = canvasWidth;
  let finalCanvasHeight = canvasHeight;
  let bgWidth = gapX + width;
  let bgHeight = gapY + height;

  if (isHexagonal) {
    finalCanvasWidth = canvasWidth * 2;
    finalCanvasHeight = canvasHeight * 2;
    bgWidth = (gapX + width) * 2;
    bgHeight = (gapY + height) * 2;
  }

  canvas.width = finalCanvasWidth;
  canvas.height = finalCanvasHeight;
  ctx.translate(offsetLeft * ratio, offsetTop * ratio);
  ctx.globalAlpha = alpha;

  // 内部绘图辅助函数
  const drawRotate = (
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    r: number
  ) => {
    ctx.translate(x, y);
    ctx.rotate((Math.PI / 180) * Number(r));
    ctx.translate(-x, -y);
  };

  const drawText = (item: WatermarkText, x: number, y: number) => {
    const {
      text,
      fontSize = 16,
      fontFamily = "normal",
      fontWeight = "normal",
    } = item;
    const fillStyle = item.fontColor || fontColor;

    ctx.font = `normal normal ${fontWeight} ${
      fontSize * ratio
    }px/${markHeight}px ${fontFamily}`;
    ctx.fillStyle = fillStyle;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(text, x, y);
  };

  // 预处理内容 (计算 top 和 totalImages)
  const contents: WatermarkItemInternal[] = (
    Array.isArray(watermarkContent)
      ? watermarkContent
      : [{ ...watermarkContent }]
  ).map((item) => ({ ...item, top: 0 }));

  let currentTop = 0;
  let totalImages = 0;

  contents.forEach((item) => {
    item.top = currentTop;
    if ("url" in item) {
      currentTop += height; // 图片固定占用 height
      totalImages += isHexagonal ? 2 : 1;
    } else if ("text" in item) {
      // 文本占用行高，使用 lineSpace 作为行间距
      const fs = item.fontSize || 16;
      currentTop += fs + lineSpace;
    }
  });

  // 绘制水印内容 (核心函数)
  let imageLoadCount = 0;
  const renderWatermarkItem = (
    item: WatermarkItemInternal,
    offsetX: number = 0,
    offsetY: number = 0,
    rotateX: number = 0,
    rotateY: number = 0
  ) => {
    // 绘制图片
    if ("url" in item) {
      const { url, isGrayscale = false } = item;
      const img = new Image();
      img.crossOrigin = "anonymous";
      img.referrerPolicy = "no-referrer";
      img.src = url;

      img.onload = () => {
        ctx.save();
        drawRotate(ctx, rotateX, rotateY, rotate);

        if (isGrayscale) {
          // 灰度处理：使用临时画布
          const tempCanvas = document.createElement("canvas");
          const tempCtx = tempCanvas.getContext("2d")!;
          tempCanvas.width = markWidth;
          tempCanvas.height = markHeight;
          tempCtx.drawImage(img, 0, 0, markWidth, markHeight);
          const imgData = tempCtx.getImageData(0, 0, markWidth, markHeight);
          const pixels = imgData.data;
          for (let i = 0; i < pixels.length; i += 4) {
            const lightness = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;
            pixels[i] = lightness;
            pixels[i + 1] = lightness;
            pixels[i + 2] = lightness;
          }
          tempCtx.putImageData(imgData, 0, 0);
          ctx.drawImage(
            tempCanvas,
            offsetX,
            offsetY + item.top * ratio,
            markWidth,
            markHeight
          );
        } else {
          ctx.drawImage(
            img,
            offsetX,
            offsetY + item.top * ratio,
            markWidth,
            markHeight
          );
        }
        ctx.restore();

        // 检查是否所有图片都加载完毕
        imageLoadCount += 1;
        if (imageLoadCount === totalImages) {
          onFinish({ base64Url: canvas.toDataURL(), bgWidth, bgHeight });
        }
      };
      img.onerror = () => {
        // 图片加载失败
        imageLoadCount += 1;
        console.warn(`水印图片加载失败: ${url}`);
        if (imageLoadCount === totalImages) {
          onFinish({ base64Url: canvas.toDataURL(), bgWidth, bgHeight });
        }
      };

      // 绘制文字
    } else if ("text" in item) {
      ctx.save();
      drawRotate(ctx, rotateX, rotateY, rotate);
      drawText(item, offsetX, offsetY + item.top * ratio);
      ctx.restore();
    }
  };

  // 执行绘制
  // 绘制标准矩形
  // 计算画布中心位置（考虑 offsetLeft 和 offsetTop）
  const centerX = (width / 2) * ratio;
  const centerY = (height / 2) * ratio;
  contents.forEach((item) => {
    renderWatermarkItem(item, centerX, centerY, centerX, centerY);
  });

  // 如果是六边形，绘制交错部分
  if (isHexagonal) {
    contents.forEach((item) => {
      renderWatermarkItem(
        item,
        canvasWidth, // x 偏移
        canvasHeight, // y 偏移
        canvasWidth, // 旋转中心 x
        canvasHeight // 旋转中心 y
      );
    });
  }

  // 同步返回 (如果没有图片)
  if (totalImages === 0) {
    onFinish({ base64Url: canvas.toDataURL(), bgWidth, bgHeight });
  }
}

/**
 * 最终的 useWatermark Hook
 * @param appendEl 水印附加的目标元素, 默认为 document.body
 */
export function useWatermark(appendEl: HTMLElement | null = document.body) {
  const watermarkId = `${watermarkIdPrefix}${++watermarkIdCounter}`;
  let resizeHandler: () => void = () => {};
  let currentOptions: UseWatermarkOptions | null = null;
  let currentWatermarkDiv: HTMLDivElement | null = null;

  const clear = () => {
    if (
      currentWatermarkDiv &&
      appendEl &&
      appendEl.contains(currentWatermarkDiv)
    ) {
      try {
        appendEl.removeChild(currentWatermarkDiv);
      } catch (error) {
        /* 忽略 */
      }
    }
    currentWatermarkDiv = null;

    if (appendEl) {
      unregisterWatermark(watermarkId, appendEl);
    }
    window.removeEventListener("resize", resizeHandler);
  };

  /**
   * 核心重绘函数 (异步)
   */
  const recreateWatermark = () => {
    if (!currentOptions || !appendEl) return;

    // 复制选项，设置默认值
    const generatorOptions: GeneratorOptions = {
      width: currentOptions.width,
      height: currentOptions.height,
      gapX: currentOptions.gapX,
      gapY: currentOptions.gapY,
      offsetLeft: currentOptions.offsetLeft ?? 0,
      offsetTop: currentOptions.offsetTop ?? 0,
      rotate: currentOptions.rotate ?? -20,
      alpha: currentOptions.alpha ?? 0.1,
      watermarkContent: currentOptions.watermarkContent,
      lineSpace: currentOptions.lineSpace ?? 16,
      fontColor: currentOptions.fontColor ?? "rgba(0,0,0,0.1)",
      layout: currentOptions.layout ?? "rectangular",
    };

    // 异步调用瓦片生成器
    _generateWatermarkTileAsync(
      generatorOptions,
      ({ base64Url, bgWidth, bgHeight }) => {
        // 回调时检查：如果在这期间 clear() 被调用, currentOptions 会是 null
        if (!base64Url || !appendEl || !currentOptions) return;

        // 在 onFinish 回调中创建或更新 DOM
        if (!currentWatermarkDiv) {
          // 首次创建
          currentWatermarkDiv = document.createElement("div");
          currentWatermarkDiv.id = watermarkId;
          // 设置不变的样式
          currentWatermarkDiv.style.pointerEvents = "none";
          currentWatermarkDiv.style.position =
            currentOptions.position ?? "fixed";
          currentWatermarkDiv.style.top = "0";
          currentWatermarkDiv.style.left = "0";
          currentWatermarkDiv.style.zIndex = String(
            currentOptions.zIndex ?? 100000000
          );
          currentWatermarkDiv.style.overflow = "hidden";

          if (currentWatermarkDiv.style.position === "absolute") {
            currentWatermarkDiv.style.width = "100%";
            currentWatermarkDiv.style.height = "100%";
          } else {
            currentWatermarkDiv.style.right = "0";
            currentWatermarkDiv.style.bottom = "0";
          }
          appendEl.appendChild(currentWatermarkDiv);
        }

        currentWatermarkDiv.style.backgroundImage = `url(${base64Url})`;
        currentWatermarkDiv.style.backgroundRepeat = "repeat";
        currentWatermarkDiv.style.backgroundSize = `${bgWidth}px ${bgHeight}px`;

        registerWatermark(watermarkId, appendEl, recreateWatermark);
      }
    );
  };

  function setWatermark(options: UseWatermarkOptions) {
    // 清理此实例的旧状态 (DOM, Observer, Resize)
    clear();

    // 存储新选项
    currentOptions = options;

    // 开始执行（异步）创建
    recreateWatermark();

    // (重新)设置 resize 监听
    resizeHandler = debounce(() => {
      setWatermark(options);
    }, 300);

    window.addEventListener("resize", resizeHandler);
  }

  return { setWatermark, clear };
}
